package com.ruoyi.web.controller.trackApply;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ExecUtil;
import com.ruoyi.common.utils.biz.BizModule;
import com.ruoyi.common.utils.biz.PathUtil;
import com.ruoyi.common.utils.biz.ResultSaveModule;
import com.ruoyi.dm.mapper.DataCollectionMapper;
import com.ruoyi.framework.datasource.DynamicDataSource;
import com.ruoyi.web.vo.MannedSpaceAssessVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.sql.Connection;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * <p>
 *  载人航天飞行器轨道大气环境监测评估
 * </p>
 *
 * @author liuhl
 * @since 2024-05-28
 */
@RestController
@RequestMapping("/mannedSpace")
@AllArgsConstructor
@Slf4j
@Api(tags = "载人航天飞行器轨道大气环境监测评估")
public class MannedSpaceAssessController {


    private DynamicDataSource dataSource;
    private DataCollectionMapper dataCollectionMapper;


    @PostMapping("/assess")
    @ApiOperation(value = "评估", notes = "根据页面输入条件评估出结果", httpMethod = "POST")
    public AjaxResult assess(@RequestBody MannedSpaceAssessVo vo) {
        String codePath = PathUtil.codeModuleDir(BizModule.TRACK_APPLY)  + PathUtil.moduleDirs().getTrackApply().get("mannedSpaceAssess");
        String command = "python "+codePath+" "+vo.getSpacecraft()+" "+vo.getStartTime()+" "+vo.getEndTime()+" "+vo.getRatio()+" "+vo.getEnv();
        String results = ExecUtil.execCmdWithResult(command);
        if (results == null || !results.contains("###")){
            return AjaxResult.error(results);
        }

        String dataJsonStr = results.split("###")[1];
        Map<String, Object> dataMap = null;
        try {
            dataMap = JSONUtil.toBean(dataJsonStr, Map.class);
        }catch (Exception e) {
            return AjaxResult.error(results);
        }
        Map<String,Object> resultMap = new HashMap<>();
        //前端的图1： 时间、观测值、模拟值
        Map<String,Object> chart1 = new HashMap<>();
        chart1.put("time", dataMap.get("time"));
        chart1.put("obs", dataMap.get("obs"));
        chart1.put("sim", dataMap.get("Jacchia71_modeled"));

        resultMap.put("chart1", chart1);
        //前端的图2： 时间、绝对误差、相对误差
        Map<String,Object> chart2 = new HashMap<>();
        chart2.put("time", dataMap.get("time"));
        chart2.put("absolute", dataMap.get("Jacchia71_abs_diff"));
        chart2.put("relative", dataMap.get("Jacchia71_rel_diff"));

        resultMap.put("chart2", chart2);
        //表： 表数据就是一行，模型写死：Jacchia71. 也就是 [{modelName: Jacchia71, absError: 7.3e-13, ...}]
        List<Map<String,Object>> tableData = new ArrayList<>();
        Map<String,Object> line = new HashMap<>();
        line.put("modelName", "Jacchia71");
        line.put("absoluteAvg", dataMap.get("mean_abs_diff"));
        line.put("relativeAvg", dataMap.get("mean_rel_diff"));
        line.put("root", dataMap.get("rmse"));
        line.put("coe", dataMap.get("r_value"));

        tableData.add(line);
        resultMap.put("tableData", tableData);
        return AjaxResult.success(resultMap);
    }

    @PostMapping("/correct")
    @ApiOperation(value = "修正", notes = "根据页面输入条件得出修正结果", httpMethod = "POST")
    public AjaxResult magneticPredict(@RequestBody MannedSpaceAssessVo vo) {
        String codePath = PathUtil.codeModuleDir(BizModule.TRACK_APPLY)  + PathUtil.moduleDirs().getTrackApply().get("mannedSpaceCorrect");
        String command = "python "+codePath+" "+vo.getSpacecraft()+" "+vo.getStartTime()+" "+vo.getEndTime()+" "+vo.getRatio()+" "+vo.getEnv() + " modify";
        String results = ExecUtil.execCmdWithResult(command);

        if (StrUtil.isBlank(results)){
            return AjaxResult.error(results);
        }
        if (results.contains("$$$")){
            String notice = results.split("\\$\\$\\$")[1];
            return AjaxResult.error(notice);
        }
        if (!results.contains("###")){
            return AjaxResult.error(results);
        }

        String dataJsonStr = results.split("###")[1];
        Map<String, Object> dataMap = null;
        try {
             dataMap = JSONUtil.toBean(dataJsonStr, Map.class);
        }catch (Exception e) {
            return AjaxResult.error(dataJsonStr);
        }

        Map<String,Object> resultMap = new HashMap<>();

        //前端的图1： 修正值
        Map<String,Object> chart1 = new HashMap<>();
        chart1.put("correct", dataMap.get("modeled"));

        resultMap.put("chart1", chart1);
        //前端的图2： 绝对误差、相对误差
        Map<String,Object> chart2 = new HashMap<>();
        chart2.put("correctAbsolute", dataMap.get("abs_diff"));
        chart2.put("correctRelative", dataMap.get("rel_diff"));

        resultMap.put("chart2", chart2);
        //表： 表数据就是一行，模型写死：Jacchia71. 也就是 [{modelName: Jacchia71, absError: 7.3e-13, ...}]
        List<Map<String,Object>> tableData = new ArrayList<>();
        Map<String,Object> line = new HashMap<>();
        line.put("modelName", "动态修正模型");
        line.put("absoluteAvg", dataMap.get("mean_abs_diff"));
        line.put("relativeAvg", dataMap.get("mean_rel_diff"));
        line.put("root", dataMap.get("rmse"));
        line.put("coe", dataMap.get("r_value"));

        tableData.add(line);
        resultMap.put("tableData", tableData);

        /***开始 生成文件保存数据 */
        String savePath = PathUtil.outputModuleDir(BizModule.TRACK_APPLY)
                + "/mannedSpace_result"
                + "/" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_FORMAT)
                + "_" + IdUtil.simpleUUID() + ".txt";

        File file = new File(savePath);
        if (file.exists()) {
            file.delete();
        }
        FileWriter.create(file).write(JSONUtil.toJsonPrettyStr(resultMap));
        /***开始 生成文件保存数据 */

        resultMap.put("resultData", JSONUtil.toJsonStr(Stream.of(savePath).collect(Collectors.toList())));
        resultMap.put("module", ResultSaveModule.TRACK_APPLY);
        resultMap.put("submodule", ResultSaveModule.TRACK_APPLY_MAN);

        return AjaxResult.success(resultMap);
    }

    @PostMapping("/forecast")
    @ApiOperation(value = "预报", notes = "根据页面输入条件得出预报结果", httpMethod = "POST")
    public AjaxResult magneticForecast(@RequestBody MannedSpaceAssessVo vo) {
        String codePath = PathUtil.codeModuleDir(BizModule.TRACK_APPLY)  + PathUtil.moduleDirs().getTrackApply().get("mannedSpaceCorrect");
        String command = "python "+codePath+" "+vo.getSpacecraft()+" "+vo.getStartTime()+" "+vo.getEndTime()+" "+vo.getRatio()+" "+vo.getEnv() + " forecast";
        String results = ExecUtil.execCmdWithResult(command);

        if (StrUtil.isBlank(results)){
            return AjaxResult.error("预报结果异常");
        }
        if (results.contains("$$$")){
            String notice = results.split("\\$\\$\\$")[1];
            return AjaxResult.error(notice);
        }
        if (!results.contains("###")){
            return AjaxResult.error(results);
        }

        String dataJsonStr = results.split("###")[1];
        Map<String, Object> dataMap = null;
        try {
            dataMap = JSONUtil.toBean(dataJsonStr, Map.class);
        }catch (Exception e) {
            return AjaxResult.error(dataJsonStr);
        }

        Map<String,Object> resultMap = new HashMap<>();

        //前端的图1： 修正值
        Map<String,Object> chart1 = new HashMap<>();
        chart1.put("correct", dataMap.get("modeled"));

        resultMap.put("chart1", chart1);
        //前端的图2： 绝对误差、相对误差
        Map<String,Object> chart2 = new HashMap<>();
        chart2.put("correctAbsolute", dataMap.get("abs_diff"));
        chart2.put("correctRelative", dataMap.get("rel_diff"));

        resultMap.put("chart2", chart2);
        //表： 表数据就是一行，模型写死：Jacchia71. 也就是 [{modelName: Jacchia71, absError: 7.3e-13, ...}]
        List<Map<String,Object>> tableData = new ArrayList<>();
        Map<String,Object> line = new HashMap<>();
        line.put("modelName", "动态预报模型");
        line.put("absoluteAvg", dataMap.get("mean_abs_diff"));
        line.put("relativeAvg", dataMap.get("mean_rel_diff"));
        line.put("root", dataMap.get("rmse"));
        line.put("coe", dataMap.get("r_value"));

        tableData.add(line);
        resultMap.put("tableData", tableData);

        return AjaxResult.success(resultMap);
    }


    @GetMapping("/spacecraft")
    @ApiOperation(value = "获取载人航天器列表", notes = "获取载人航天器列表", httpMethod = "GET")
    public AjaxResult getSpacecraftList() throws Exception{

        String schemaName ;
        Connection connection = null;
        try{
            connection = dataSource.getConnection();
            String schema = connection.getSchema();
            if (StrUtil.isNotBlank(schema)){
                schemaName = schema;
            }else {
                schemaName = connection.getMetaData().getUserName();
            }
            List<String> tableNames = dataCollectionMapper.selectAllTableNames(schemaName.toLowerCase()); //大写最好
            if (CollUtil.isEmpty(tableNames)){
                return AjaxResult.error("模式: {} 下没有找到任何数据库表");
            }
            List<String> finalTables = tableNames
                    .stream()
                    .map(String::toUpperCase)
                    .filter(name -> name.contains("SWDATA_OBS_DEN_"))
                    .filter(name -> !name.contains("GRACEA_SZ2")
                            && !name.contains("GRACEA_GRACEB")
                            && !name.contains("_FUSION")
                    )
                    .collect(Collectors.toList());

            if (CollUtil.isEmpty(finalTables)){
                return AjaxResult.error("模式: {} 下没有找到任何符合搜索条件的数据库表");
            }
            Map<String, String> resultMap = finalTables.stream()
                    .map(o -> o.replace("SWDATA_OBS_DEN_", ""))
                    .collect(TreeMap::new, (map,data) -> {
                        map.put(data,data);
                    }, TreeMap::putAll);
            return AjaxResult.success(resultMap);
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }finally {
            if (connection!=null){
                connection.close();
            }
        }

    }


}
